package com.jrx.anytxn.param.job.bactchBillCompare.config;

import com.jrx.anytxn.common.uitl.DateUtils;
import com.jrx.anytxn.common.uitl.FileUtils;
import com.jrx.anytxn.common.uitl.StringUtils;
import com.jrx.anytxn.number.service.ISegmentService;
import com.jrx.anytxn.param.config.BillCompareConfig;
import com.jrx.anytxn.param.config.PathFileConfig;
import com.jrx.anytxn.param.constant.Constant;
import com.jrx.anytxn.param.entity.PrOrganizationTable;
import com.jrx.anytxn.param.entity.TlThirdBillDetail;
import com.jrx.anytxn.param.entity.TlThirdBillSummary;
import com.jrx.anytxn.param.job.bactchBillCompare.bean.ThirdFileNameBean;
import com.jrx.anytxn.param.mapper.ext.ExtTlThirdBillDetailMapper;
import com.jrx.anytxn.param.mapper.ext.ExtTlThirdBillSummaryMapper;
import com.jrx.anytxn.param.service.system.IOrganizationTableService;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StopWatch;

import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 三方对账-外部文件数据落库
 *
 * @author : llk
 * 2020/11/26
 */
@Configuration
@EnableConfigurationProperties(PathFileConfig.class)
public class BatchThirdBillFileReadConfiguration {

    private static final Logger logger = LoggerFactory.getLogger(BatchThirdBillFileReadConfiguration.class);

    @Autowired
    public JobBuilderFactory jobBuilderFactory;

    @Autowired
    public StepBuilderFactory stepBuilderFactory;

    @Autowired
    private IOrganizationTableService organizationTableService;

    @Autowired
    private ISegmentService iSegmentService;

    @Resource
    private ExtTlThirdBillSummaryMapper extTlBillThirdSummaryMapper;

    @Resource
    private ExtTlThirdBillDetailMapper extTlBillThirdDetailMapper;

    @Autowired
    private BillCompareConfig billCompareConfig;

    @Bean
    public Job readerThirdBillFileJob() throws IOException {
        return jobBuilderFactory.get("readerThirdBillFileJob")
                .start(readerTransactionFileStep())
                .build();
    }

    @Bean
    public Step readerTransactionFileStep() throws IOException {
        return stepBuilderFactory.get("readerTransactionFileStep").tasklet(readerTransactionFileTasklet()).build();
    }

    @Bean
    public Tasklet readerTransactionFileTasklet() {
        return (stepContribution, chunkContext) -> {

            StopWatch stopWatch = new StopWatch("文件读取耗时统计");

            PrOrganizationTable org = organizationTableService.findByOrgIdForBatch(Constant.XIB_ORG_NUMBER);
            // 设置指定对账日期
            Date today = billCompareConfig.getToday();
            if (Objects.nonNull(today)) {
                org.setToday(today);
            }
            String fileDate = DateUtils.format(org.getToday(), DateUtils.DATE_PATTERN_ANOTHER);
            String businessDate = DateUtils.format(org.getToday());

            String thirdChannel = billCompareConfig.getThirdChannel();
            String path = billCompareConfig.getFilePath() + File.separator + thirdChannel + File.separator + "transaction" + File.separator + fileDate;

            logger.info("交易流水文件读取开始，渠道号:{} 业务日期为:{} 路径为:{} ", thirdChannel, businessDate, path);
            extTlBillThirdDetailMapper.deleteByDealDate(DateUtils.format(org.getToday()), thirdChannel);
            extTlBillThirdSummaryMapper.deleteByBusDate(org.getToday(), thirdChannel);

            List<TlThirdBillDetail> detailList = new LinkedList<>();

            Predicate<File> fileFilter = file -> {
                String name = file.getName();
                if (name.contains(billCompareConfig.getThirdChannel()) && name.contains("transaction") && name.contains(fileDate) && name.contains(".txt")) {
                    return true;
                }
                return false;
            };
            List<File> files = FileUtils.findFiles(path).stream().filter(fileFilter).collect(Collectors.toList());

            for (File file : files) {
                logger.info("开始处理 : {}", file.getName());
                stopWatch.start(file.getName());
                ThirdFileNameBean bean = buildFileName(file.getName());
                InputStreamReader reader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8); // 建立一个输入流对象reader
                BufferedReader br = new BufferedReader(reader); // 建立一个对象，它把文件内容转成计算机能读懂的语言\
                String line = br.readLine();
                //当天没有交易
                logger.info("头部行 : {}", line);
                if (null == line || 0 == line.length()) {
                    logger.info("空文件不处理  路径为:{}", path);
                    return null;
                }

                TlThirdBillSummary summary = buildSummary(bean, org, line, iSegmentService.getId(Constant.TL_THIRD_BILL_DETAIL_TABLE));
                extTlBillThirdSummaryMapper.insertSelective(summary);

                while ((line = br.readLine()) != null) {
                    logger.info("数据行 : {}", line);
                    if (0 == line.length()) {
                        logger.warn("存在为空的一行数据");
                        continue;
                    }

                    TlThirdBillDetail detail = buildDetail(bean, org, line, iSegmentService.getId(Constant.TL_THIRD_BILL_SUMMARY_TABLE));
                    logger.info(detail.toString());
                    detailList.add(detail);

                    if (detailList.size() == 5000) {
                        detailList.forEach(d -> extTlBillThirdDetailMapper.insertSelective(d));
                        detailList.clear();
                    }
                }

                if (CollectionUtils.isNotEmpty(detailList)) {
                    detailList.forEach(d -> extTlBillThirdDetailMapper.insertSelective(d));
                }
                stopWatch.stop();
                logger.info("交易流水文件读取结束 文件名:{}  路径:{}", file.getName(), file.getPath());
            }
            if (CollectionUtils.isNotEmpty(files)) {
                logger.info("交易流水文件读取完毕 业务日:{}  文件数量:{} 路径:{} \n {}", businessDate, files.size(), path, stopWatch.prettyPrint());
            } else {
                logger.info("交易流水文件为空    业务日:{}              路径:{} \n {}", businessDate, path, stopWatch.prettyPrint());
            }
            return RepeatStatus.FINISHED;

        };
    }


    private ThirdFileNameBean buildFileName(String fileName) {
        String[] split = fileName.trim().split("\\.", -1);
        String[] params = split[0].split("\\_", -1);
        ThirdFileNameBean bean = new ThirdFileNameBean();
        bean.setThirdChannel(params[0]);
        bean.setBusDate(params[1]);
        bean.setBatchNumber(params[2]);
        return bean;
    }

    private TlThirdBillSummary buildSummary(ThirdFileNameBean bean, PrOrganizationTable org, String line, long id) {

        TlThirdBillSummary summary = new TlThirdBillSummary();
        summary.setId(id);
        summary.setTenantId(org.getTenantId());
        summary.setOrganizationId(org.getOrganizationId());
        summary.setThirdChannel(billCompareConfig.getThirdChannel());
        summary.setBatchNumber(bean.getBatchNumber());
        String[] params = line.trim().split("\\|", -1);
        summary.setBusinessDate(DateUtils.parseDate(params[0], DateUtils.DATE_PATTERN_ANOTHER));

        summary.setTotalCount(Integer.parseInt(params[1]));
        summary.setTotalAmount(new BigDecimal(params[2]));

        summary.setConsumptionCount(Integer.parseInt(params[3]));
        summary.setConsumptionSuccessCount(Integer.parseInt(params[4]));
        summary.setConsumptionAmount(new BigDecimal(params[5]));
        summary.setConsumptionSuccessAmount(new BigDecimal(params[6]));

        summary.setReturnCount(Integer.parseInt(params[7]));
        summary.setReturnSuccessCount(Integer.parseInt(params[8]));
        summary.setReturnAmount(new BigDecimal(params[9]));
        summary.setReturnSuccessAmount(new BigDecimal(params[10]));

        summary.setRectificationCount(Integer.parseInt(params[11]));
        summary.setRectificationSuccessCount(Integer.parseInt(params[12]));
        summary.setRectificationAmount(new BigDecimal(params[13]));
        summary.setRectificationSuccessAmount(new BigDecimal(params[14]));

        summary.setRevokeCount(Integer.parseInt(params[15]));
        summary.setRevokeSuccessCount(Integer.parseInt(params[16]));
        summary.setRevokeAmount(new BigDecimal(params[17]));
        summary.setRevokeSuccessAmount(new BigDecimal(params[18]));

        return summary;
    }

    private TlThirdBillDetail buildDetail(ThirdFileNameBean bean, PrOrganizationTable org, String line, long id) {

        TlThirdBillDetail detail = new TlThirdBillDetail();
        detail.setId(id);
        detail.setTenantId(org.getTenantId());
        detail.setOrganizationId(org.getOrganizationId());
        detail.setThirdChannel(billCompareConfig.getThirdChannel());
        detail.setBatchNumber(bean.getBatchNumber());
        String[] params = line.trim().split("\\|", -1);

        if (StringUtils.isNotBlank(params[0])) {
            detail.setThirdSeq(params[0]);
        }

        if (StringUtils.isNotBlank(params[1])) {
            detail.setThirdTime(DateUtils.parseDate(params[1], DateUtils.PART_DATETIME_PATTERN));
        }

        if (StringUtils.isNotBlank(params[2])) {
            detail.setBusinessDate(DateUtils.parseDate(params[2], DateUtils.DATE_PATTERN_ANOTHER));
        }

        if (StringUtils.isNotBlank(params[3])) {
            detail.setTransactionAmount(new BigDecimal(params[3]));
        }

        if (StringUtils.isNotBlank(params[4])) {
            detail.setTransactionType(params[4]);
        }

        if (StringUtils.isNotBlank(params[5])) {
            detail.setTransStatus(params[5]);
        }

        if (StringUtils.isNotBlank(params[6])) {
            detail.setCoreSeq(params[6]);
        }

        if (StringUtils.isNotBlank(params[7])) {
            detail.setCoreBusDate(params[7]);
        }

        if (params.length >= 9 && StringUtils.isNotBlank(params[8])) {
            detail.setOrgThirdSeq(params[8]);
        }
        detail.setDealDate(org.getToday());
        detail.setCompareFlag(Constant.COMPARE_FLAG_0);
        return detail;
    }

}